package auth

import (
	//"errors"
	"github.com/astaxie/beego/orm"
	"github.com/casbin/casbin/model"
	"github.com/casbin/casbin/persist"
	//"github.com/lib/pq"
	"runtime"
	"strings"
)

type CasbinRule struct {
	Id    int
	UserName     string
	Url         string
	Method    	     string
}

func init() {

	orm.RegisterDriver("mysql", orm.DRMySQL)
}

// Adapter represents the Xorm adapter for policy storage.
type Adapter struct {
	driverName     string
	dataSourceName string
	dbSpecified    bool
	o              orm.Ormer
}


// finalizer is the destructor for Adapter.
func finalizer(a *Adapter) {
}


// NewAdapter is the constructor for Adapter.
// dbSpecified is an optional bool parameter. The default value is false.
// It's up to whether you have specified an existing DB in dataSourceName.
// If dbSpecified == true, you need to make sure the DB in dataSourceName exists.
// If dbSpecified == false, the adapter will automatically create a DB named "casbin".
func (aa *Adapter) NewAdapter() *Adapter {
	a := &Adapter{}
	// Open the DB, create it if not existed.
	// a.open()

	// Call the destructor when the object is released.
	runtime.SetFinalizer(a, finalizer)

	return a
}

func (a *Adapter) registerDataBase(aliasName, driverName, dataSource string, params ...int) error {
	err := orm.RegisterDataBase(aliasName, driverName, dataSource, params...)
	if err != nil && strings.HasSuffix(err.Error(), "already registered, cannot reuse") {
		return nil
	}
	return err
}

func (a *Adapter) createDatabase() error {
	/*var err error
	var o orm.Ormer
	if a.driverName == "postgres" {
		err = a.registerDataBase("create_casbin", a.driverName, a.dataSourceName + " dbname=postgres")
	} else {
		err = a.registerDataBase("create_casbin", a.driverName, a.dataSourceName)
	}
	if err != nil {
		return err
	}
	o = orm.NewOrm()

	if a.driverName == "postgres" {
		if 		_, err = o.Raw("CREATE DATABASE casbin").Exec(); err != nil {
			// 42P04 is	duplicate_database
			if err.(*pq.Error).Code == "42P04" {
				return nil
			}
		}
	} else {
		_, err = o.Raw("CREATE DATABASE IF NOT EXISTS casbin").Exec()
	}*/
	return nil
}

func (a *Adapter) open() {

	// a.createTable()
}

func (a *Adapter) close() {
	a.o = nil
}

func (a *Adapter) createTable() {

}

func (a *Adapter) dropTable() {

}

func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error  {
	return nil
}

// RemovePolicy removes a policy rule from the storage.
func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
	return nil
}


// RemoveFilteredPolicy removes policy rules that match the filter from the storage.
func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
	return nil
}

func savePolicyLine(ptype string, rule []string) CasbinRule {
	line := CasbinRule{}

	return line
}


// SavePolicy saves policy to database.
func (a *Adapter) SavePolicy(model model.Model) error {
	return nil
}


// LoadPolicy loads policy from database.
func (a *Adapter) LoadPolicy(model model.Model) error {
	var sql = "SELECT " +
				"usr.id," +
				"usr.username," +
				"par.url," +
				"men.perms as method" +
			" FROM" +
				"t_sys_role_menu menu" +
			" LEFT JOIN " +
				"t_sys_role rol " +
			" ON " +
				"menu.role_id = rol.ID " +
			" LEFT JOIN " +
				"t_sys_user_role ur " +
			" ON " +
				"rol.ID = ur.role_id" +
			" LEFT JOIN " +
				"t_sys_user usr " +
			" ON " +
				"ur.user_id = usr.ID " +
			" LEFT JOIN " +
				"t_sys_menu men " +
			" ON " +
				"menu.menu_id = men.ID" +
			" LEFT JOIN" +
				"t_sys_menu par" +
			" ON " +
				"men.parent_id = par.id" +
			" WHERE" +
				"menu.type = 2"
	o := orm.NewOrm()
	var lines []CasbinRule
	_, err := o.Raw(sql).QueryRows(&lines)
	if err != nil {
		return err
	}

	for _, line := range lines {
		loadPolicyLine(line, model)
	}
	return nil
}

func loadPolicyLine(line CasbinRule, model model.Model) {


	lineText := line.Url

	lineText += line.Method

	persist.LoadPolicyLine(lineText, model)
}